//
//  main.m
//  07 - 内存管理
//
//  Created by 韩旭 on 16/7/12.
//  Copyright © 2016年 基础. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Man.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //      内存问题
        //       一. 内存泄漏（溢出）内存里面东西太多导致溢出, 会产生程序Crash
        //       二. 内存野指针（过度释放）
        //        指针指向一个未知的区域, 指针指向一个被释放的内存
        //        野指针：0f0xsdf
        //        内存管理方法
        //        1 垃圾回收机制：只有Mac上有
        //        IOS:
        //        2 MRC：手动管理机制引用计数
        //        3 ARC：自动管理机制引用计数（现在常用的）
        //      注意：  ARC基于MRC进行管理，系统帮程序员添加了内存管理的内容
        //        遇到 ：retain 、alloc 、copy 需要进行内存管理
        //        NSObject *obje = [[NSObject alloc] init];
        //        [obje retain];
        //        [obje release];
        //        [obje release];
        //        [obje release];
        //       内存管理 ：引用计数 (计数器)
        //      有retain、alloc、copy 需要对引用计数 + 1
        //        有release 、 autorelease 会对引用计数 - 1
        //        当对象的计数器为0的时候， 系统会调用对应的dealloc方法
        //        注意：内存管理, 你对象操作完成后，在进行释放
        Man *man = [[Man alloc] init];
        [man retain];
        [man release];
        NSLog(@"%ld", man.retainCount);
        //        集合类型会对, 对象进行引用计数有影响
        //        addobject 对 对象进行引用计数 + 1
        //        removeObject 对 对象进行引用计数 - 1
        NSMutableArray *arrMan = [NSMutableArray arrayWithObjects:man,  nil];
        NSLog(@"向数组中添加后的引用计数 %ld", man.retainCount);
        [arrMan removeAllObjects];
        NSLog(@"%ld",man.retainCount);
        //        2.ARC
        //        strong (ARC, 强引用, 引用计数+1) 语义特性
        //        weak (应用的是对象类型（NSObject子类），弱引用，对象被释放时, 会自动置空)
        //        retain（MRC, 强引用, 引用计数+1）
        //        copy（拷贝, 把对象拷贝一份 原来的引用计数不变，新的+1）
        //        assign（应用于简单的数据类型，不会产生引用计数）
        //        协议 ,
        //        1. 声明协议， 声明协议方法h
        //        2. 签订协议
        //        3. 实现协议方法
        //          [man copy];
        //        如果想实现对象的拷贝
        //        1. 签订协议方法NSCopying
        //        2. 实现协议方法CopyWithZone
        Man *newMan = [man copy];
        NSLog(@"%@", newMan);
        //        浅拷贝
        newMan.name = @"啊蔚";
        newMan.sexual = @"女";
        //        kvc key - value - Coding 键值编码 间接访问成员的方式
        //        只要是NSObject的子类就包含这些方法
        //        valueForKey
        //        valueForKey
        //        setValue: forkey
        //        setValue: forKeyPath
        id name = [newMan valueForKey:@"name"];
        NSLog(@"%@", name);
        [newMan setValue:@"徐康" forKey:@"name"];
        NSLog(@"%@", newMan.name);
        Man *gayMan = [[Man alloc] init];
        gayMan.gayBoy = newMan;
        id boyName = [gayMan valueForKeyPath:@"gayBoy.name"];
        NSLog(@"++++++%@", boyName);
        [gayMan release];
        [gayMan setValue:@"李四" forKeyPath:@"gayBoy.name"];
        NSLog(@"%@", gayMan.gayBoy.name);
        //
        NSMutableDictionary *dic = [NSMutableDictionary dictionary];
        [dic setValue:@"张三" forKey:@"name"];
        NSLog(@"%@", dic);
        NSDictionary *dicc = [[NSDictionary alloc] initWithObjectsAndKeys:@"12345",@"ID", @"疯狂", @"des", nil];
        Man *dicMan = [[Man alloc] init];
        [dicMan setValuesForKeysWithDictionary:dicc];
        //         加在Build Phases下的编译source下
        //        如果在ARC工程下使用MRC的文件
        //        -fno-objc-arc
        //        在mrc的工程下使用ARC的文件
        //        -fobjc-arc
    }
    return 0;
}
